/**
 * 维护登录账号信息
 */
import { getLogger, Service } from '@gnlab/utils'
import { makeHTTPSAvatar } from '@/lib/https'
import type { Services } from '@/services'
import type { Account, AuthMethod } from '@/services/auth'
import { Permission } from '@/services/auth'
import { API } from '@/services/common/api'

const logger = getLogger('services/features/accounts')

/**
 * 接口返回的账号信息
 */
interface RawAccount {
  id: string
  username: string
  createdAt: string
  phone: string
  avatar: string
  Remark: string | null
  IsAdmin: boolean
  Permissions: Permission[]
}
function formatRawAccounts(authMethod: AuthMethod, rawList: RawAccount[]): Account[] {
  // 此处参考了 services/auth/definition 里 formatRespAccount() 的格式化处理
  const parentId = rawList.find(v => v.IsAdmin)?.id ?? `${authMethod}-0`
  const rawParentId = parseInt(parentId.split('-')[1] ?? '0', 10)
  return rawList.map(raw => ({
    id: raw.id,
    rawId: parseInt(raw.id.split('-')[1] ?? '0', 10),
    parentId: raw.IsAdmin ? null : parentId,
    rawParentId: raw.IsAdmin ? null : rawParentId,
    name: raw.username || raw.phone,
    avatar: makeHTTPSAvatar(raw.avatar),
    remark: raw.Remark ?? '',
    token: '',
    isAdmin: raw.IsAdmin || raw.Permissions.includes(Permission.Admin),
    isSuperAdmin: raw.IsAdmin,
    permissions: raw.Permissions,
    method: authMethod,
  }))
}

// 获取当前账号和子账号的信息列表
export async function getAccounts(current: Account, token?: string) {
  const { method: authMethod, id: currentId } = current
  return API('/User/UserList', {
    token,
    formatter(items: RawAccount[]) {
      return formatRawAccounts(authMethod, items).sort(item => (item.id === currentId ? -1 : 1)) // 让当前账号排在最前面
    },
  })
}

export class Accounts extends Service<Services> {
  private get auth() {
    return this.services.auth
  }

  /**
   * 返回全部可用账号列表
   * 此方法会缓存接口数据，调用时无需担心性能
   *
   * refresh: 若为 true 则忽略缓存强制调用接口
   */
  protected _accounts: null | Account[] = null
  async getAccounts(refresh = false) {
    if (!this._accounts || refresh) {
      const res = await getAccounts(this.auth.account$.value!)
      if (res.success) {
        this._accounts = res.data
      } else {
        this._accounts = []
        logger.warn('加载账号列表失败', res.error)
      }
    }
    return this._accounts
  }

  /**
   * 获取指定账号的权限列表（限管理员调用）
   */
  async getPermissions(accountId: string) {
    const res = await API<{ Permissions: Permission[] }>('/Permission/GetUserPermissions', {
      data: { UserId: accountId },
    })
    if (res.success) {
      return res.data.Permissions
    } else {
      logger.warn('获取用户权限列表失败', res.error)
      return []
    }
  }

  /**
   * 给用户添加权限
   */
  async addPermission(accountId: string, permission: Permission) {
    return API('/Permission/AddUserPermission', {
      data: { UserId: accountId, Permission: permission },
    })
  }

  /**
   * 移除用户的权限
   */
  async removePermission(accountId: string, permission: Permission) {
    return API('/Permission/RemoveUserPermission', {
      data: { UserId: accountId, Permission: permission },
    })
  }

  /**
   * 返回所有账号分组
   */
  async getGroups() {
    const res = await API<RespAccountGroup[]>('/UserGroup/UserGroupList')
    if (res.success) {
      return res.data.map(formatAccountGroup)
    } else {
      logger.warn('用户分组加载失败', res.error)
      return []
    }
  }

  /**
   * 创建一个账号分组
   */
  async addGroup(name: string) {
    const res = await API('/UserGroup/AddOrUpdateUserGroup', { data: { GroupName: name } })
    if (res.success) return true
    else return res.error
  }

  /**
   * 修改账号分组
   */
  async updateGroup(group: AccountGroup) {
    const requestGroup = {
      Id: group.id,
      GroupName: group.name,
      UserGroupUsers: group.accountIds.map(id => ({ UserId: id })),
    }
    const res = await API('/UserGroup/AddOrUpdateUserGroup', { data: requestGroup })
    if (res.success) return true
    else return res.error
  }

  /**
   * 向分组里添加成员（基于 updateGroup()）
   */
  async groupAddAccounts(group: AccountGroup, accountIds: string[]) {
    return this.updateGroup({
      ...group,
      accountIds: [...new Set([...group.accountIds, ...accountIds])],
    })
  }

  /**
   * 移除分组里的指定成员（基于 updateGroup()）
   */
  async groupRemoveAccounts(group: AccountGroup, accountIds: string[]) {
    return this.updateGroup({
      ...group,
      accountIds: group.accountIds.filter(id => !accountIds.includes(id)),
    })
  }

  /**
   * 删除账号分组
   */
  async removeGroup(id: number) {
    const res = await API('/UserGroup/RemoveUserGroup', { data: { Id: id } })
    if (res.success) return true
    else return res.error
  }
}

interface RespAccountGroup {
  Id: number
  GroupName: string
  UserGroupUsers: { UserId: string }[]
}
export interface AccountGroup {
  id: number
  name: string
  accountIds: string[]
}
function formatAccountGroup(raw: RespAccountGroup): AccountGroup {
  return {
    id: raw.Id,
    name: raw.GroupName,
    accountIds: raw.UserGroupUsers.map(v => v.UserId),
  }
}
